home *** CD-ROM | disk | FTP | other *** search
- /*************************************************************************************************
- *
- *
- * MacZoop - "the framework for the rest of us"
- *
- *
- *
- * ZComrade.cpp -- an object that can maintain loose links between objects
- *
- *
- *
- *
- *
- * © 1996, Graham Cox
- *
- *
- *
- *
- *************************************************************************************************/
-
-
- #include "ZComrade.h"
- #include "ZObjectArray.cpp"
- #include "MacZoop.h"
-
-
- // this is a fudge to get around a limitation of the language- ZComrade requires ZObjectArray
- // for its lists, but ZObjectArray IS a ZComrade. Thus, since we are not allowed forward/
- // circular cross-dependencies like this, this struct is used to "pull" the declaration forward
- // so that everything compiles correctly.
-
- struct ZComradeList : ZObjectArray<ZComrade>
- {
- };
-
-
- CLASSCONSTRUCTOR( ZComrade );
-
- /*---------------------------------*** CONSTRUCTOR ***--------------------------------*/
-
-
- ZComrade::ZComrade()
- {
- classID = CLASS_ZComrade;
- talkers = listeners = NULL;
- }
-
- /*---------------------------------*** DESTRUCTOR ***---------------------------------*/
-
- ZComrade::~ZComrade()
- {
- // when we are destroyed, we need to make sure that we remove ourselves
- // from any talker's list that we are part of, and make sure that any listeners
- // that are listening to us no longer do so.
-
- long n;
- ZComrade* aComrade;
-
- if( listeners )
- {
- n = listeners->CountItems();
-
- do
- {
- aComrade = listeners->GetObject( n );
-
- if( aComrade )
- aComrade->RemoveTalker( this );
- }
- while( --n );
-
- ForgetObject( listeners );
- }
-
- if( talkers )
- {
- n = talkers->CountItems();
-
- do
- {
- aComrade = talkers->GetObject( n );
-
- if( aComrade )
- aComrade->RemoveListener( this );
- }
- while( --n );
-
- ForgetObject( talkers );
- }
- }
-
-
- /*--------------------------------*** SENDMESSAGE ***---------------------------------*/
- /*
- transmit a message to anyone who is listening
- ----------------------------------------------------------------------------------------*/
-
- void ZComrade::SendMessage( long aMessage, void* msgData )
- {
- // send the message to all of the listeners of this object
-
- long n;
- ZComrade* aListener;
-
- if( listeners )
- {
- n = listeners->CountItems();
-
- do
- {
- aListener = listeners->GetObject( n );
-
- if( aListener )
- aListener->ReceiveMessage( this, aMessage, msgData );
- }
- while( --n );
- }
- }
-
- /*--------------------------------*** SENDMESSAGE ***---------------------------------*/
- /*
- transmit a message to anyone who is listening (via a message object)
- ----------------------------------------------------------------------------------------*/
-
- void ZComrade::SendMessage( ZMessage* aMessage )
- {
- // send the message object to all of the listeners of this object
-
- long n;
- ZComrade* aListener;
-
- if( listeners )
- {
- n = listeners->CountItems();
-
- do
- {
- aListener = listeners->GetObject( n );
-
- if( aListener )
- aListener->ReceiveMessage( this, aMessage );
- }
- while( --n );
- }
- }
-
-
- /*-------------------------------*** RECEIVEMESSAGE ***-------------------------------*/
- /*
- a message was transmitted by someone we have earlier elected to listen to
- ----------------------------------------------------------------------------------------*/
-
- void ZComrade::ReceiveMessage( ZComrade* aSender, long theMessage, void* msgData )
- {
- // override to do something useful
- }
-
-
- /*------------------------------*** RECEIVEMESSAGE ***--------------------------------*/
- /*
- receive a message in a message object from one of our transmitting comrades
- ----------------------------------------------------------------------------------------*/
-
- void ZComrade::ReceiveMessage( ZComrade* aSender, ZMessage* aMessage )
- {
- // override to do something useful
- }
-
- /*---------------------------------*** LISTENTO ***-----------------------------------*/
- /*
- elect to listen to another comrade. We will receive any messages transmitted by that
- object whenever it sends them
- ----------------------------------------------------------------------------------------*/
-
- void ZComrade::ListenTo( ZComrade* aSender )
- {
- // add this to the sender's list of listeners, and the sender to our list of talkers
-
- FailOSErr((aSender == NULL)? paramErr : noErr );
-
- // make sure we are not already listening to this one- references must be
- // included exactly once
-
- if(( talkers == NULL ) || !talkers->Contains( aSender ))
- {
- aSender->AddListener( this );
- AddTalker( aSender );
- }
- }
-
-
- /*-----------------------------*** STOPLISTENINGTO ***-------------------------------*/
- /*
- we no longer want to receive messages from this transmitter
- ----------------------------------------------------------------------------------------*/
-
- void ZComrade::StopListeningTo( ZComrade* aSender )
- {
- // remove this from the sender's list of listeners, and remove it from our list of talkers
-
- FailOSErr((aSender == NULL)? paramErr : noErr );
-
- // make sure we are really listening to it
-
- if (talkers && talkers->Contains( aSender ))
- {
- RemoveTalker( aSender );
- aSender->RemoveListener( this );
- }
- }
-
-
- /*---------------------------------*** ADDTALKER ***----------------------------------*/
- /*
- add a talker to our list of talkers
- ----------------------------------------------------------------------------------------*/
-
- void ZComrade::AddTalker( ZComrade* aTalker )
- {
- // add the talker to the list of talkers
-
- if (talkers == NULL)
- FailNIL( talkers = new ZComradeList());
-
- talkers->AppendItem( aTalker );
- }
-
- /*-------------------------------*** ADDLISTENER ***----------------------------------*/
- /*
- add a listener to our list of listeners
- ----------------------------------------------------------------------------------------*/
-
- void ZComrade::AddListener( ZComrade* aListener )
- {
- // add the listener to the list of listeners
-
- if (listeners == NULL)
- FailNIL( listeners = new ZComradeList());
-
- listeners->AppendItem( aListener );
- }
-
-
- /*--------------------------------*** REMOVETALKER ***--------------------------------*/
- /*
- remove the talker from our list of talkers
- ----------------------------------------------------------------------------------------*/
-
- void ZComrade::RemoveTalker( ZComrade* aTalker )
- {
- // remove this talker from the list of talkers
-
- if( talkers )
- {
- talkers->DeleteObject( aTalker );
-
- if( talkers->CountItems() <= 0 )
- ForgetObject( talkers );
- }
- }
-
-
- /*-------------------------------*** REMOVELISTENER ***-------------------------------*/
- /*
- remove the listener from our list of listeners
- ----------------------------------------------------------------------------------------*/
-
- void ZComrade::RemoveListener( ZComrade* aListener )
- {
- // remove this listener from the list of listeners
-
- if( listeners )
- {
- listeners->DeleteObject( aListener );
-
- if( listeners->CountItems() <= 0 )
- ForgetObject( listeners );
- }
- }
-
-
- /*--------------------------------*** WRITETOSTREAM ***-------------------------------*/
- /*
- write talkers and listener refs to stream
- ----------------------------------------------------------------------------------------*/
-
- void ZComrade::WriteToStream( ZStream* aStream )
- {
- #if _MACZOOP_STREAMS
- // note: ZStream permits NULL objects to be written to the stream, so we don't even
- // need to check whether they're NULL or not.
-
- aStream->WriteObject( talkers );
- aStream->WriteObject( listeners );
- #endif
- }
-
-
- /*-------------------------------*** READFROMSTREAM ***-------------------------------*/
- /*
- read from the stream- this re-establishes the entire comrade linkage from the stream.
- You should only call this when this comrade is first made, since any existing talkers
- or listeners objects will be left dangling.
- ----------------------------------------------------------------------------------------*/
-
- void ZComrade::ReadFromStream( ZStream* aStream )
- {
- #if _MACZOOP_STREAMS
- talkers = (ZComradeList*) aStream->ReadObject();
- listeners = (ZComradeList*) aStream->ReadObject();
- #endif
- }
-